function info = h5info ( hdf5file )
% H5INFO  Get information about an HDF5 file.

info = [];

[info.Filename, fid] = set_filename ( hdf5file );
info.LibVersion = set_lib_version;
info.Offset = set_offset ( fid  );
info = set_filesize ( info, fid );
info.GroupHierarchy = set_group_info ( info, fid, '/' );

return

%==========================================================================
function [Filename, fid] = set_filename ( hdf5file )
% Set the filename field and make sure we can access the file normally.
if ~ exist ( hdf5file, 'file' )
	error ( 'MATLAB:H5INFO:fileDoesNotExist', ...
	        '%s does not exist.', hdf5file );
end


fid = fopen ( hdf5file, 'r' );
Filename = fopen ( fid );
fclose ( fid );
info.Filename = Filename;

fid = H5F.open ( Filename, 'H5F_ACC_RDONLY', 'H5P_DEFAULT' );




%==========================================================================
function LibVersion = set_lib_version ()
[majnum,minnum,relnum] = H5.get_libversion();
LibVersion = sprintf ( '%d.%d.%d', majnum, minnum, relnum );
return

%==========================================================================
function offset = set_offset ( fid )
% Get the offset, also known as the "user-block" from a file creation 
% property list.
plist = H5F.get_create_plist ( fid );
offset = H5P.get_userblock ( plist );
H5P.close(plist);
return


%==========================================================================
function info = set_filesize ( info, fid )
info.Filesize = H5F.get_filesize ( fid );
return




%==========================================================================
function group_info = set_group_info ( parent_info, loc_id, groupname )
% Need to set seven fields, 
%
%   1.  Filename
%   2.  Name
%   3.  Groups
%   4.  Datasets
%   5.  Datatypes
%   6.  Links
%   7.  Attributes

group_info.Filename = parent_info.Filename;

%
% Set the group name properly.
if ~isfield(parent_info, 'Name' )
	group_info.Name = groupname;
elseif strcmp(parent_info.Name,'/')
	group_info.Name = sprintf ( '/%s', groupname );
else
	group_info.Name = sprintf ( '%s/%s', parent_info.Name, groupname );
end

nobjs = H5G.get_num_objs ( loc_id );

group_count = 0;
dataset_count = 0;

for idx = 0:nobjs-1
	obj_type = H5G.get_objtype_by_idx ( loc_id, idx );
    objname = H5G.get_objname_by_idx ( loc_id, 0 );
	switch (obj_type)

		case 1 % group
			group_count = group_count + 1;
			gid = H5G.open ( loc_id, objname );
			Groups(group_count) = set_group_info ( group_info, gid, objname );
			H5G.close(gid);

		case 2 % dataset
			dataset_count = dataset_count + 1;
			Datasets(dataset_count) = set_dataset ( group_info, loc_id, objname );

		otherwise
			error ( 'MATLAB:h5info:setGroupInfo', ...
			        'unhandled object type ''%d''', obj_type );
			
	end
end

%
% If we didn't find any datasets in this group, then the 'Datasets' variable
% was never created.
if exist('Datasets','var') == 0
	group_info.Datasets = [];
else
	group_info.Datasets = Datasets;
end

%
% If we didn't find any groups in this group, then the 'Groups' variable
% was never created.
if exist('Groups','var') == 0
	group_info.Groups = [];
else
	group_info.Groups = Groups;
end
return


%==========================================================================
function Dataset = set_dataset ( parent_group, loc_id, dataset_name )
% SET_DATASET
%
% Need to set eleven fields.
%
% 1.  Filename
% 2.  Name
% 3.  Rank
% 4.  Datatype
% 5.  Dims
% 6.  MaxDims
% 7.  Layout
% 8.  Attributes
% 9.  Links
% 10. Chunksize
% 11. FillValue
fprintf ( 2, 'set_datasets not yet finished.\n' );

Dataset.Filename = parent_group.Filename;
Dataset.Name = sprintf ( '%s/%s', parent_group.Name, dataset_name );
dset_id = H5D.open ( loc_id, dataset_name );

dspace_id = H5D.get_space ( dset_id );
Dataset.Rank = H5S.get_simple_extent_ndims ( dspace_id );
Dataset.Datatype = get_datatype ( dset_id );
H5S.close ( dspace_id );

H5D.close ( dset_id );

return

%==========================================================================
function Datatype = get_datatype ( dataset_id )

dtype = H5D.get_type ( dataset_id );

Datatype.Class = dtype;


return
